﻿
// #define DEBUG_DRAW

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Diagnostics;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Physics;

namespace Tank
{
    public class SetUpScreen: Screen
    {
        List<Player> playerList;                            // List of Player Indexes who are playing in this game
        bool[] selectStartArray;                              // Array of players that have joined. Index corresponds to PlayerIndexs
        string[] playerSelectionArray;

        // Graphics Objects    
        Graphic2D background;
        Graphic2D[] avatarArray;
        Graphic2D[] tankChoiceArray;
        Graphic2D[] levelArray;
        Graphic2D[] levelMessage;
        Graphic2D[] messageArray;
        Graphic2D[] cursorArray;
        float cursorSpeed;

        public SetUpScreen(int _width, int _height)
            : base(_width, _height)
        {
            InitPlayerLists();

            width = _width;
            height = _height;
            cursorSpeed = 15.0f;

            InitGraphics();
        }

        private void InitPlayerLists()
        {
            playerList = new List<Player>();

            // No tanks selected initially
            playerSelectionArray = new string[4];
            for (int i = 0; i < playerSelectionArray.Length; ++i)
                playerSelectionArray[i] = "none";

            // No players have joined in until they press start
            selectStartArray = new bool[4];
            for (int i = 0; i < selectStartArray.Length; ++i)
                selectStartArray[i] = false;
        }


        public void InitGraphics()
        {
            avatarArray = new Graphic2D[4];
            messageArray = new Graphic2D[4];
            cursorArray = new Graphic2D[4];
            tankChoiceArray = new Graphic2D[4];
            levelArray = new Graphic2D[1];
            levelMessage = new Graphic2D[1];
            Vector2 playerFrameSize = new Vector2(160, 200);
            

            //=======================================================================================
            // Background graphic
            //=======================================================================================
            background = new Graphic2D(new Vector2(width*0.5f, height*0.5f), new Vector2(width, height));
            background.AddFrame("SetupScreen", "background", new Rectangle(39, 10, 1279, 719), true);

            //=======================================================================================
            // Player Avatar Graphics (current selection)
            //=======================================================================================
            Vector2 pos1 = new Vector2(170, 190);
            Graphic2D player1 = new Graphic2D(pos1, new Vector2(playerFrameSize.X, playerFrameSize.Y));
            player1.AddFrame("SetupScreen", "p1empty", new Rectangle(81, 1093, 276, 280), true);
            avatarArray[0] = player1;

            Vector2 pos2 = new Vector2(1106, 190);
            Graphic2D player2 = new Graphic2D(pos2, new Vector2(playerFrameSize.X, playerFrameSize.Y));
            player2.AddFrame("SetupScreen", "p2empty", new Rectangle(396, 1093, 276, 280), true);
            avatarArray[1] = player2;

            Vector2 pos3 = new Vector2(170, 523);
            Graphic2D player3 = new Graphic2D(pos3, new Vector2(playerFrameSize.X, playerFrameSize.Y));
            player3.AddFrame("SetupScreen", "p3empty", new Rectangle(682, 1093, 276, 280), true);
            avatarArray[2] = player3;

            Vector2 pos4 = new Vector2(1106, 523);
            Graphic2D player4 = new Graphic2D(pos4, new Vector2(playerFrameSize.X, playerFrameSize.Y));
            player4.AddFrame("SetupScreen", "p4empty", new Rectangle(997, 1093, 276, 280), true);
            avatarArray[3] = player4;

            //=======================================================================================
            // Tank Choices
            //=======================================================================================
            Vector2 tankFrameSize = new Vector2(100,140);
            Vector2 tankPos1 = new Vector2(0.315f * width, 0.315f * height);
            Graphic2D tank1 = new Graphic2D(tankPos1, new Vector2(tankFrameSize.X, tankFrameSize.Y));
            tank1.AddFrame("Tanks", "tank1", new Rectangle(1, 134, 255, 436), true);
            tankChoiceArray[0] = tank1;

            Vector2 tankPos2 = new Vector2(0.44f * width, 0.265f * height);
            Graphic2D tank2 = new Graphic2D(tankPos2, new Vector2(tankFrameSize.X, tankFrameSize.Y));
            tank2.AddFrame("Tanks", "tank2", new Rectangle(305, 103, 255, 468), true);
            tankChoiceArray[1] = tank2;

            Vector2 tankPos3 = new Vector2(0.565f * width, 0.265f * height);
            Graphic2D tank3 = new Graphic2D(tankPos3, new Vector2(tankFrameSize.X, tankFrameSize.Y));
            tank3.AddFrame("Tanks", "tank3", new Rectangle(610, 100, 255, 472), true);
            tankChoiceArray[2] = tank3;

            Vector2 tankPos4 = new Vector2(0.69f * width, 0.315f * height);
            Graphic2D tank4 = new Graphic2D(tankPos4, new Vector2(tankFrameSize.X, tankFrameSize.Y));
            tank4.AddFrame("Tanks", "tank4", new Rectangle(914, 89, 255, 482), true);
            tankChoiceArray[3] = tank4;

            //=======================================================================================
            // Levels
            //=======================================================================================
            Vector2 levelFrameSize = new Vector2(430, 290);
            Vector2 levelPos1 = new Vector2(0.5f * width, 0.70f * height);
            Graphic2D gridLevel = new Graphic2D(levelPos1, new Vector2(levelFrameSize.X, levelFrameSize.Y));
            gridLevel.AddFrame("New-Tron", "board", new Rectangle(45, 45, 1281, 721), true);
            levelArray[0] = gridLevel;

            // Level Messages
            Vector2 levelTextSize = new Vector2(200, 150);
            Vector2 levelTextPos1 = new Vector2(0.5f * width, 0.70f * height);
            Graphic2D random = new Graphic2D(levelTextPos1, new Vector2(levelTextSize.X, levelTextSize.Y));
            random.AddFrame("New-Tron", "board", new Rectangle(1677, 42, 304, 137), true);
            levelMessage[0] = random;

            //=======================================================================================
            // Text Messages
            //=======================================================================================
            Vector2 message1Pos = new Vector2(0.14f * width, 0.47f * height);
            Graphic2D message1 = new Graphic2D(message1Pos, new Vector2(210, 30));
            message1.AddFrame("SetupScreen", "pressStart", new Rectangle(54, 946, 293, 47), true);
            message1.AddFrame("SetupScreen", "selectTank", new Rectangle(357, 945, 163, 32), false);
            message1.AddFrame("SetupScreen", "confirm", new Rectangle(361, 989, 290, 47), false);
            message1.AddFrame("SetupScreen", "wait", new Rectangle(56, 1007, 256, 37), false);
            messageArray[0] = message1;

            Vector2 message2Pos = new Vector2(0.89f * width, 0.47f * height);
            Graphic2D message2 = new Graphic2D(message2Pos, new Vector2(210, 30));
            message2.AddFrame("SetupScreen", "pressStart", new Rectangle(54, 946, 293, 47), true);
            message2.AddFrame("SetupScreen", "selectTank", new Rectangle(357, 945, 163, 32), false);
            message2.AddFrame("SetupScreen", "confirm", new Rectangle(361, 989, 290, 47), false);
            message2.AddFrame("SetupScreen", "wait", new Rectangle(56, 1007, 256, 37), false);
            messageArray[1] = message2;

            Vector2 message3Pos = new Vector2(0.15f * width, 0.94f * height);
            Graphic2D message3 = new Graphic2D(message3Pos, new Vector2(210, 30));
            message3.AddFrame("SetupScreen", "pressStart", new Rectangle(54, 946, 293, 47), true);
            message3.AddFrame("SetupScreen", "selectTank", new Rectangle(357, 945, 163, 32), false);
            message3.AddFrame("SetupScreen", "confirm", new Rectangle(361, 989, 290, 47), false);
            message3.AddFrame("SetupScreen", "wait", new Rectangle(56, 1007, 256, 37), false);
            messageArray[2] = message3;

            Vector2 message4Pos = new Vector2(0.89f * width, 0.94f * height);
            Graphic2D message4 = new Graphic2D(message4Pos, new Vector2(210, 30));
            message4.AddFrame("SetupScreen", "pressStart", new Rectangle(54, 946, 293, 47), true);
            message4.AddFrame("SetupScreen", "selectTank", new Rectangle(357, 945, 163, 32), false);
            message4.AddFrame("SetupScreen", "confirm", new Rectangle(361, 989, 290, 47), false);
            message4.AddFrame("SetupScreen", "wait", new Rectangle(56, 1007, 256, 37), false);
            messageArray[3] = message4;

            //=======================================================================================
            // Cursors for players
            //=======================================================================================
            for (int i = 0; i < cursorArray.Length; ++i)
            {
                Vector2 cursorPos = new Vector2(0.5f * width, 0.5f * height);
                Graphic2D cursor = new Graphic2D(cursorPos, new Vector2(50, 50));
                cursor.AddFrame("SetupScreen", "player1", new Rectangle(942, 922, 145, 145), true);

                cursorArray[i] = cursor;
            }
        }

        public override void Update(float deltaTime)
        {
            if (sceneOver)
                return;

            UpdateUserInput();
        }

        public void UpdateUserInput()
        {
            // Loop through each game pad and see if anyone has pressed the 'Start' button, if so, they are now playing
            if (Input.Instance.UsingGamePad)
            {
                List<PlayerIndex> connectedControllers = Input.Instance.GetConnectedControllers();
                foreach (PlayerIndex indx in connectedControllers)
                {
                    UpdateGamepad(indx);
                }

                sceneOver = true;
                foreach (PlayerIndex indx in connectedControllers)
                {
                    if (messageArray[(int)indx].FrameID != "wait")
                    {
                        sceneOver = false;
                        break;
                    }
                }
            }
            // Using Keyboard
            else
            {
                UpdateKeyboard();
            }
        }

        private void UpdateGamepad(PlayerIndex indx)
        {
            // Start Button
            if (Input.Instance.DidButtonJustGoDown(Microsoft.Xna.Framework.Input.Buttons.Start, indx))
            {
                // Check if a new player pressed start
                if (IsPlayerInList(indx) == false)
                {
                    Player player = new Player(indx);
                    playerList.Add(player);

                    // Assign color to rectical
                    Debug.Assert(cursorArray.Length == 4);
                    cursorArray[(int)indx].BaseColor = player.PlayerColor;
                }

                // Is this the first time the start button is pressed
                if (selectStartArray[(int)indx] == false)
                {
                    selectStartArray[(int)indx] = true;
                    messageArray[(int)indx].SetFame("selectTank");
                }
                // Is a tank selected
                else
                {
                    if (messageArray[(int)indx].FrameID == "confirm")
                    {
                        messageArray[(int)indx].FrameID = "wait";
                    }
                }
            }

            // A Button
            if (Input.Instance.DidButtonJustGoDown(Buttons.A, indx))
            {
                if (selectStartArray[(int)indx])        // Has player pressed start
                { 
                    foreach(Graphic2D tank in tankChoiceArray)
                    {
                        if (PhysicsBase.PointInRect2D(cursorArray[(int)indx].Position, tank.DestinationRect))
                        {
                            SoundManager.Instance.PlaySound(SoundType.BUTTON_CLICK);
                            avatarArray[(int)indx].AddFrame(tank.CurrentTextureID, tank.FrameID, tank.SourceRect, true);
                            Color playerColor = Color.White;
                            Player currPlayer = null;
                            foreach (Player player in playerList)
                            {
                                if (player.PlayerIndexID == indx)
                                {
                                    currPlayer = player;
                                    break;
                                }
                            }
                            Debug.Assert(currPlayer != null);
                            avatarArray[(int)indx].BaseColor = currPlayer.PlayerColor;
                            playerSelectionArray[(int)indx] = tank.FrameID;
                            if(selectStartArray[(int)indx] == true)
                            {
                                messageArray[(int)indx].SetFame("confirm");
                            }

                            // Debug
#if DEBUG_DRAW
                            selectStartArray[1] = true;
                            avatarArray[1].AddFrame(tank.CurrentTextureID, tank.FrameID, tank.SourceRect, true);
                            playerSelectionArray[1] = tank.FrameID;

                            selectStartArray[2] = true;
                            avatarArray[2].AddFrame(tank.CurrentTextureID, tank.FrameID, tank.SourceRect, true);
                            playerSelectionArray[2] = tank.FrameID;

                            selectStartArray[3] = true;
                            avatarArray[3].AddFrame(tank.CurrentTextureID, tank.FrameID, tank.SourceRect, true);
                            playerSelectionArray[3] = tank.FrameID;

#endif // DEBUG_DRAW
                        }
                    }
                    
                }
            }

            // Thumb control movement
            Vector2 leftStickPos = Input.Instance.GetLeftThumbStick(indx);
            if (leftStickPos.X != 0 || leftStickPos.Y != 0)
            {
                float magnitude = leftStickPos.Length();
                leftStickPos.Normalize();
                leftStickPos.Y *= -1;
                Vector2 currCursorPos = cursorArray[(int)indx].Position;

                // Keep Cursor Inside of Screen
                currCursorPos += (leftStickPos * magnitude * cursorSpeed);
                if (currCursorPos.X > width)
                    currCursorPos.X = width;
                else if (currCursorPos.X < 0)
                    currCursorPos.X = 0;
                if (currCursorPos.Y < 0)
                    currCursorPos.Y = 0;
                else if (currCursorPos.Y > height)
                    currCursorPos.Y = height;
                cursorArray[(int)indx].Position = currCursorPos;

                
            }
        }

        private void UpdateKeyboard()
        {
            if (Input.Instance.DidKeyJustGoDown(Keys.Enter))
            {
                Player player1 = new Player(PlayerIndex.One);
                Player player2 = new Player(PlayerIndex.Two);
                playerList.Add(player1);
                playerList.Add(player2);
                sceneOver = true;
                
                // Hardcode tank selection
                playerSelectionArray[0] = "tank1";
                playerSelectionArray[1] = "tank1";

            }
        }

        public override void Draw(SpriteBatch sb)
        {
            // Draw background
            background.Draw(sb);

            // Draw Graphics in Dictionary (selections)
            for(int i = 0; i < avatarArray.Length; ++i)
            {
                // Only show avatar if they have pressed start
                if(selectStartArray[i])
                {
                    avatarArray[i].Draw(sb);
                }
            }
            // Text messages
            foreach (Graphic2D graphic in messageArray)
            {
                graphic.Draw(sb);
            }
            // Tank choices
            foreach (Graphic2D graphic in tankChoiceArray)
            {
                graphic.Draw(sb);
            }
            // Level Graphics
            foreach (Graphic2D graphic in levelArray)
            {
                graphic.Draw(sb);
            }
            // Level Messages
            foreach (Graphic2D graphic in levelMessage)
            {
                graphic.Draw(sb);
            }
            // Cursors
            for (int i = 0; i < cursorArray.Length; ++i)
            {
                if (selectStartArray[i])         // Only show cursor if player has pressed start
                {
                    cursorArray[i].Draw(sb);
                }
            }
        }

        private bool IsPlayerInList(PlayerIndex indx)
        {
            for (int i = 0; i < playerList.Count; ++i)
            {
                if (playerList[i].PlayerIndexID == indx)
                    return true;
            }
            return false;            
        }

        public List<Player> GetPlayerList()
        {
            return playerList;
        }

        public string[] GetTankChoices()
        {
            Debug.Assert(playerSelectionArray != null);
            Debug.Assert(playerSelectionArray.Length == 4);
            return playerSelectionArray;
        }

        public override void ResetScreen()
        {
            sceneOver = false;
            InitPlayerLists();
            InitGraphics();
        }

    }
}
